<?php
/**
 * Базы данных
 * 
 * Класс для работы с базами
 * @author Anton Zavidov
 * @package myLiveShop
 */

/**
 * Базовый класс для работы с базами
 *
 */
abstract class DB extends Base {
	/**
	 * Тип данных число
	 *
	 */
	const TYPE_INT="int";
	/**
	 * Тип данных строка
	 *
	 */
	const TYPE_STRING="string";
	/**
	 * Тип данных объект
	 *
	 */
	const TYPE_OBJECT="object";
	/**
	 * Продолжать при ошибке
	 *
	 * @var unknown_type
	 */
	public static $exit_on_error=true;
	/**
	 * Инстанс класа
	 *
	 * @var DB
	 */
	protected static $instance;
	/**
	 * Конект к базе данных
	 *
	 */
	abstract public function connect();
	/**
	 * Закрываем конект к базе
	 *
	 */
	abstract public function close();
	/**
	 * Запрос к базе
	 *
	 * @param string $query строка запроса
	 */
	abstract public function query($query);
	/**
	 * Вставка данных
	 *
	 * @param string $query строка запроса
	 */
	abstract public function insert($table,$data,$params=false);
	/**
	 * Последний ID
	 *
	 * @return int
	 */
	abstract public function lastId();
	/**
	 * Изменение данных
	 *
	 * @param string $query строка запроса
	 */
	abstract public function update($table,$data,$where='');
	/**
	 * Удаление данных
	 *
	 * @param string $query строка запроса
	 */
	abstract public function delete($table,$where);
	/**
	 * Возвращает true если база подконекчена
	 * 
	 */
	abstract public function isConnect();
	/**
	 * Обрабатываем данные перед сохранением и возвращаем их тип
	 *
	 * @param mixed $value ссылка на данные
	 * @return string тип данных (int/string/object) или false если не удалось определить тип
	 */
	public function prepareData(&$value){
		if(is_numeric($value))return self::TYPE_INT;
		if(is_string($value))$type=self::TYPE_STRING;
		elseif(is_array($value) || is_object($value))$type=self::TYPE_OBJECT;
		else{
			return false;
		}
		$this->eraseData($value,$type);
		return $type;
	}
	/**
	 * Поличение инстанса класса
	 *
	 * @return DB
	 */
	public static function getInstance() {
		if (self::$instance === null)
		return self::$instance = new self();
		else
		return self::$instance;
	}
	/**
	 * Очищаем данные в соответствии с типом
	 *
	 * @param mixed $value ссылка на данные
	 * @param string $type тип данных (int/string/object)
	 */
	public function eraseData(&$value,$type='auto'){
		switch ($type) {
			case self::TYPE_STRING:
				$value='"'.$this->escaped($value).'"';
				break;
			case self::TYPE_OBJECT:
				$value='"'.serialize($value).'"';
				break;
			case self::TYPE_INT:break;
			case 'auto':
				if(is_string($value))$this->eraseData($value,self::TYPE_STRING);
				elseif(is_numeric($value))$this->eraseData($value,self::TYPE_INT);
				elseif(is_array($value) || is_object($value))$this->eraseData($value,self::TYPE_OBJECT);
				elseif(is_bool($value))$value=(int)$value;
				else $this->eraseData($value,'uincom');
				break;
			default:
				//если тип неизвестен кидаем исключение
				new CoreExeption('Неизвестный тип данных для обработки ('.$type.')',E_WARNING,__FILE__,__LINE__,array('type'=>$type,'value'=>$value));
				break;
		}
		return $value;
	}
	/**
	 * Ставим апостофы
	 *
	 * @param string $value
	 * @return string
	 */
	public static function apostrof($value){
		if(is_object($value)){
			new CoreExeption('Неверный тип данных для обработки',E_WARNING,__FILE__,__LINE__,array('value'=>$value));
			return $value;
		}
		if($value[0]=='`')return $value;
		return '`'.str_replace('.','`.`',$value).'`';
	}
	/**
	 * Защитить данные
	 *
	 * @param string $value
	 */
	abstract public function escaped($value);
	/**
	 * Получить массив данных по запросу
	 *
	 * @param mixed $var либо строка запроса либо ресурс
	 */
	abstract public function getArray($var);
}